/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.editor; import javax.swing.text.BadLocationException; import javax.swing.text.Document; /** * Support class for chain of MarkBlocks * * @author Miloslav Metelka * @version 1.00 */ public class MarkChain { /** Chain of all marks */ protected MarkFactory.ChainDrawMark chain; /** Current mark to make checks faster */ protected MarkFactory.ChainDrawMark curMark; /** Document for this mark */ protected BaseDocument doc; /** If this chain uses draw marks, then this is the name for the draw layer * that will be used for the marks */ protected String layerName; /** Construct chain using draw marks */ public MarkChain(BaseDocument doc, String layerName) { this.doc = doc; this.layerName = layerName; } public final MarkFactory.ChainDrawMark getChain() { return chain; } public final MarkFactory.ChainDrawMark getCurMark() { return curMark; } /** Tests whether the position range is partly or fully inside * some mark block from the chain. * @param pos compared position * @return relation of curMark to the given position */ public int compareMark(int pos) { try { if (curMark == null) { curMark = chain; if (curMark == null) { return -1; // no marks yet } } int rel; boolean after = false; boolean before = false; while ((rel = curMark.compare(pos)) != 0) { // just match if (rel > 0) { // this mark after pos if (before) { return rel; } if (curMark.prev != null) { after = true; curMark = curMark.prev; } else { // end of chain return rel; } } else { // this mark before pos if (after) { return rel; } if (curMark.next != null) { before = true; curMark = curMark.next; } else { // start of chain return rel; } } } return 0; // match } catch (InvalidMarkException e) { if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N e.printStackTrace(); } return -1; // don't match, but what to return? } } protected MarkFactory.ChainDrawMark createAndInsertNewMark(int pos) throws BadLocationException { MarkFactory.ChainDrawMark mark = createMark(); try { doc.op.insertMark(mark, pos); } catch (InvalidMarkException e) { if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N e.printStackTrace(); } } return mark; } protected MarkFactory.ChainDrawMark createMark() { MarkFactory.ChainDrawMark mark = new MarkFactory.ChainDrawMark(layerName, null); mark.insertAfter = true; // stay at line begining mark.activateLayer = true; return mark; } /** Add mark to the chain * @return true if the mark was added * false if there's already mark at that pos */ public boolean addMark(int pos) throws BadLocationException { int rel = compareMark(pos); if (rel == 0) { return false; // already exists } else if (rel > 0) { // curMark after pos MarkFactory.ChainDrawMark mark = createAndInsertNewMark(pos); if (curMark != null) { if (curMark == chain) { // curMark is first mark chain = curMark.insertChain(mark); } else { // curMark is not first mark curMark.insertChain(mark); } } else { // no marks in chain chain = mark; } } else { // curMark before pos MarkFactory.ChainDrawMark mark = createAndInsertNewMark(pos); if (curMark != null) { if (curMark.next != null) { curMark.next.insertChain(mark); } else { // last mark in chain curMark.setNextChain(mark); } } else { // no marks in chain chain = mark; } } return true; } /** Remove non-empty block from area covered by blocks from chain */ public boolean removeMark(int pos) { int rel = compareMark(pos); if (rel == 0) { boolean first = (curMark == chain); curMark = curMark.removeChain(); if (first) { chain = curMark; } return true; } else { // not found return false; } } /** Is there mark at given position? */ public boolean isMark(int pos) { return (compareMark(pos) == 0); } /** Toggle the mark so that if it didn't exist it is created * and if it existed it's removed * @return true if the new mark was added * false if the existing mark was removed */ public boolean toggleMark(int pos) throws BadLocationException { int rel = compareMark(pos); if (rel == 0) { // exists removeMark(pos); return false; } else { // didn't exist addMark(pos); return true; } } public String toString() { return "MarkChain: curMark=" + curMark + ", mark chain: " // NOI18N + (chain != null ? ("\n" + chain.toStringChain()) : "Empty"); // NOI18N } } /* * Log * 10 Gandalf-post-FCS1.8.1.0 3/8/00 Miloslav Metelka * 9 Gandalf 1.8 1/13/00 Miloslav Metelka * 8 Gandalf 1.7 1/10/00 Miloslav Metelka * 7 Gandalf 1.6 11/14/99 Miloslav Metelka * 6 Gandalf 1.5 11/8/99 Miloslav Metelka * 5 Gandalf 1.4 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 4 Gandalf 1.3 10/10/99 Miloslav Metelka * 3 Gandalf 1.2 3/23/99 Miloslav Metelka * 2 Gandalf 1.1 3/18/99 Miloslav Metelka * 1 Gandalf 1.0 3/18/99 Miloslav Metelka * $ */